﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Timers;
using System.IO;

namespace HostDetector
{
    class HostFinder
    {
        PacketAnalyser pa;
        Pinger pinger;
        public delegate void HostHandler(string host);
        public event HostHandler HostIPFoundEvent;
        public event HostHandler HostNameFoundEvent;

        public delegate void PingHandler(long ping);
        public event PingHandler PingEvent;

        Deobfuscator deob = new Deobfuscator();

        HashSet<IPEndPoint> potentialHosts = new HashSet<IPEndPoint>();
        Dictionary<IPEndPoint, byte[]> pings = new Dictionary<IPEndPoint, byte[]>(10000);
        byte[] partyBytes = Encoding.ASCII.GetBytes("partystate");
        IPAddress[] localIPs;


        Player[] currentPlayers = new Player[18];

        public Player[] CurrentPlayers
        {
            get { return currentPlayers; }
        }


        
        public HostFinder()
        {
            pa = new PacketAnalyser();
            pa.Big6Event += new PacketAnalyser.DataPacketHandler(pa_Big6Event);


            pa.PingMessageEvent += new PacketAnalyser.PingMessageHandler(pa_PingMessageEvent);
            pinger = new Pinger();
            pinger.PingEvent += new Pinger.PingHandler(pinger_PingEvent);
            localIPs = Dns.GetHostAddresses(Dns.GetHostName());


        }







        void pa_Big6Event(IPEndPoint src, IPEndPoint dst, byte[] data)
        {



            if (deob.decodePacket(data, src))
            {

                bool partyFound = true;
                for (int i = 0; i < partyBytes.Length; i++)
                    if (data[21 + i] != partyBytes[i])
                    {
                        partyFound = false;
                        break;
                    }

                if (partyFound)
                {
                    Console.WriteLine("Party State " + src + " -> " + dst);
                    PartyState ps = new PartyState(data);
                    foreach (Player p in ps.Players)
                    {
                        currentPlayers[p.PlayerID] = p;
                    }
                    foundHost(src);

                }

            }
            

                

        }




        void pa_PingMessageEvent(IPEndPoint address, byte[] message)
        {

            if (!pings.ContainsKey(address))
                pings.Add(address, message);

        }

        void pinger_PingEvent(long ping)
        {
            PingEvent(ping);
        }


        private void foundHost(IPEndPoint endPoint)
        {
            if (pings.ContainsKey(endPoint))
            {
                pinger.PingMessage = pings[endPoint];
                pinger.Ip = endPoint;
            }

            
            if (localIPs.Contains(endPoint.Address))
            {
                HostNameFoundEvent("You are the host!");
            }
            else
            {

                foreach (Player player in currentPlayers)
                {
                    if (player != null && player.Ip.Equals(endPoint))
                    {

                        HostNameFoundEvent(player.Name);
                        break;
                    }
                }
            }
            HostIPFoundEvent(endPoint.ToString());
        }

        
    }
}
